package com.panda.mall.elastic.service.impl;

import com.alibaba.fastjson.JSON;
import com.panda.mall.common.constants.ConfigConstants;
import com.panda.mall.common.mallOrder.entity.MallOrder;
import com.panda.mall.common.mallOrder.feign.OrderFeign;
import com.panda.mall.common.mallWares.entity.MallGoodsCategory;
import com.panda.mall.common.mallWares.entity.MallGoodsSpuInfo;
import com.panda.mall.common.mallWares.feign.CategoryFeign;
import com.panda.mall.common.result.Result;
import com.panda.mall.common.result.ServiceException;
import com.panda.mall.elastic.service.ElasticService;
import com.panda.mall.elastic.utils.ParseDataUtil;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * author: tcy
 * createDate: 2023/3/2
 * description:
 */
@Service
public class ElasticServiceImpl implements ElasticService {

    @Autowired
    RestHighLevelClient restHighLevelClient;

    @Autowired
    ParseDataUtil parseDataUtil;

    @Autowired
    OrderFeign orderFeign;

    @Autowired
    CategoryFeign categoryFeign;

    /**
     * 创建ES索引
     * @param keyword
     * @return
     */
    @Override
    public String createIndex(String keyword) {

        //1.创建索引请求
        CreateIndexRequest indexRequest = new CreateIndexRequest(keyword);
        //2.执行请求
        try {
            CreateIndexResponse indexResponse = restHighLevelClient.indices().create(indexRequest, RequestOptions.DEFAULT);

            return indexResponse.isShardsAcknowledged() ? "创建成功" : "创建失败";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "操作失败";
    }

    /**
     * 删除ES索引
     * @param keyword
     * @return
     */
    @Override
    public String deleteIndex(String keyword) {

        //1.删除索引请求
        DeleteIndexRequest request = new DeleteIndexRequest(keyword);
        //2.执行请求
        try {
            AcknowledgedResponse response = restHighLevelClient.indices().delete(request,RequestOptions.DEFAULT);

            return response.isAcknowledged() ? "删除成功" : "删除失败";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "操作失败";
    }

    /**
     * 查询ES索引
     * @param keyword
     * @return
     */
    @Override
    public String queryIndex(String keyword) {

        //1.查询索引请求
        GetIndexRequest request = new GetIndexRequest(keyword);
        //2.执行请求
        try {
            boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);

            return exists ? "存在索引" : "不存在索引";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "操作失败";
    }

    /**
     * 查询全部索引
     * @return
     */
    @Override
    public List<String> listIndex() {

        List<String>  result = new LinkedList<>();

        //1.查询索引请求
        GetIndexRequest request = new GetIndexRequest("*");

        try {
            GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);

            String[] indices = response.getIndices();
            List<String> list = Arrays.stream(indices).filter(item -> !item.startsWith(".")).collect(Collectors.toList());

            result.addAll(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 批量创建ES文档
     * @param keyword
     * @param index
     * @return
     */
    @Override
    public String createDocument(String keyword, String index) {

        try {
            //1.创建批量操作请求
            BulkRequest request = new BulkRequest();
            //请求超时设置
            request.timeout("10s");

            //2.文档数据
            if (ConfigConstants.INDEX_jingDong.equals(index)){
                //拉取京东的数据
                List<MallGoodsSpuInfo> goodsSpuInfos = parseDataUtil.parseData(keyword);

                //遍历添加至请求
                for (int i = 0; i < goodsSpuInfos.size(); i++) {
                    request.add(new IndexRequest(index).source(JSON.toJSONString(goodsSpuInfos.get(i)), XContentType.JSON).id(i+1+""));
                }
            }
            if (ConfigConstants.INDEX_order.equals(index)){
                //拉取订单的数据
                List<MallOrder> orders = orderFeign.queryOrders().getData();
                //遍历添加至请求
                for (MallOrder order:orders) {
                    request.add(new IndexRequest(index).source(JSON.toJSONString(order), XContentType.JSON));
                }
            }
            if (ConfigConstants.INDEX_category.equals(index)){
                //拉取商品的数据
                List<MallGoodsCategory> categories = categoryFeign.queryCategory().getData();
                //遍历添加至请求
                for (MallGoodsCategory category : categories) {
                    request.add(new IndexRequest(index).source(JSON.toJSONString(category), XContentType.JSON));
                }
            }
            //4.执行请求
            BulkResponse bulk = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
            boolean failures = bulk.hasFailures();
            return failures ? "批量创建文档失败" : "批量创建文档成功成功" ;
        }catch (Exception e){
            e.printStackTrace();
        }
        return "操作失败";
    }

    /**
     * 条件搜索ES文档
     * @param keyword
     * @param index
     * @return
     */
    @Override
    public List<Map<String,Object>> searchDocument(String keyword, String index) {

        //1.创建搜索请求
        SearchRequest request = new SearchRequest(index);

        //2.构建搜索条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        HighlightBuilder builder = new HighlightBuilder();
        builder.preTags("<font color = 'red'>");
        builder.postTags("</font>");

        /**
         * QueryBuilders.termQuery()      精确匹配
         * QueryBuilders.matchAllQuery()  匹配所有
         * QueryBuilders.matchQuery()     模糊匹配
         */
        MatchQueryBuilder matchQuery = null;
        if (ConfigConstants.INDEX_jingDong.equals(index)){
            matchQuery = QueryBuilders.matchQuery("supName",keyword);
            builder.field("supName");
        }
        if (ConfigConstants.INDEX_order.equals(index)){
            matchQuery = QueryBuilders.matchQuery("userName",keyword);
            builder.field("userName");
        }
        if (ConfigConstants.INDEX_category.equals(index)){
            matchQuery = QueryBuilders.matchQuery("categoryName",keyword);
            builder.field("categoryName");
        }

        sourceBuilder.highlighter(builder);                                   //高亮
        sourceBuilder.query(matchQuery);                                      //查询条件
        sourceBuilder.from(0);                                                //起始页
        sourceBuilder.size(10);                                               //每页数量
        sourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS));   //超时上限
        request.source(sourceBuilder);

        //3.执行查询请求
        try {
            SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            List<Map<String,Object>> maps = new ArrayList<>();
            //遍历
            for (SearchHit documentFields:search.getHits()){
                Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
                sourceAsMap.put("eid",documentFields.getId());
                sourceAsMap.put("score",documentFields.getScore());
                sourceAsMap.put("index",documentFields.getIndex());

                //高亮设置
                Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
                StringBuilder stringBuilder = new StringBuilder();
                if (ConfigConstants.INDEX_jingDong.equals(index)){
                    Text[] texts = highlightFields.get("supName").fragments();
                    for (Text text : texts) {
                        stringBuilder.append(text);
                    }
                    sourceAsMap.put("supName",stringBuilder.toString());
                }
                if (ConfigConstants.INDEX_order.equals(index)){
                    Text[] texts = highlightFields.get("userName").fragments();
                    for (Text text : texts) {
                        stringBuilder.append(text);
                    }
                    sourceAsMap.put("userName",stringBuilder.toString());
                }
                if (ConfigConstants.INDEX_category.equals(index)){
                    Text[] texts = highlightFields.get("categoryName").fragments();
                    for (Text text : texts) {
                        stringBuilder.append(text);
                    }
                    sourceAsMap.put("category",stringBuilder.toString());
                }
                maps.add(sourceAsMap);
            }
            return maps;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 创建文档
     * @param id
     * @param index
     * @return
     */
    @Override
    public String addDocument(Long id, String index) {

        //1.创建请求
        IndexRequest request = new IndexRequest(index);

        //2.查询增加的数据
        if (ConfigConstants.INDEX_order.equals(index)){
            MallOrder mallOrder = orderFeign.queryOrderById(id).getData();
            //3.数据库信息转换JSON添加
            request.source(JSON.toJSONString(mallOrder),XContentType.JSON);
            request.timeout("1s");
        }
        if (ConfigConstants.INDEX_category.equals(index)){
            MallGoodsCategory category = categoryFeign.queryCategoryById(id).getData();
            //3.数据库信息转换JSON添加
            request.source(JSON.toJSONString(category),XContentType.JSON);
        }

        //4.客户端执行请求
        try {
            IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);

            return response.status().toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "操作失败";
    }

    /**
     * 查询文档
     * @param eid
     * @param index
     * @return
     */
    @Override
    public Map<String, Object> queryDocument(String eid, String index) {

        //1.创建请求
        GetRequest request = new GetRequest(index,eid);

        //2.执行请求
        try {
            GetResponse documentFields = restHighLevelClient.get(request, RequestOptions.DEFAULT);

            return documentFields.getSource();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 修改文档
     * @param eid
     * @param index
     * @return
     */
    @Override
    public String updateDocument(Long id, String eid, String index) {

        //1.建立请求
        UpdateRequest request = new UpdateRequest(index,eid);

        //2.修改信息
        if (ConfigConstants.INDEX_order.equals(index)){
            MallOrder mallOrder = orderFeign.queryOrderById(id).getData();
            request.doc(JSON.toJSONString(mallOrder), XContentType.JSON);
        }
        if (ConfigConstants.INDEX_category.equals(index)){
            MallGoodsCategory category = categoryFeign.queryCategoryById(id).getData();
            request.doc(JSON.toJSONString(category), XContentType.JSON);
        }

        //3.执行请求
        try {
            UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);

            return response.status().toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "操作失败";
    }

    /**
     * 删除文档
     * @param eid
     * @param index
     * @return
     */
    @Override
    public String deleteDocument(String eid, String index) {

        //1.创建请求
        DeleteRequest request = new DeleteRequest(index,eid);

        //2.执行请求
        try {
            DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);

            return response.status().toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "操作失败";
    }

}
